import json
import random
import re
import logging

from django.contrib.auth import login, authenticate, logout
from django.core.files.base import ContentFile

from ihome.libs.captcha.captcha import captcha
from ihome.utils.qiniuyun.qiniu_storage import storage
from ihome.utils.views import LoginRequiredMixin
from users.models import User
from users.utils import verify_identification_card_info

logger = logging.getLogger('django')
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render

# Create your views here.
from django.views import View
from django_redis import get_redis_connection
from celery_tasks.sms.tasks import ccp_send_sms_code

class ImageCodeView(View):
    '''定义图形验证码视图类'''
    def get(self,request):
        # 1.调用工具类 captcha 生成图形验证码
        cur = request.GET.get('cur')
        text,image = captcha.generate_captcha()
        #2 创建redis连接对象
        redis_conn = get_redis_connection('verify_code')

        # 3.利用链接对象, 保存数据到 redis, 使用 setex 函数
        redis_conn.setex('img_%s' % cur, 300, text)

        return HttpResponse(image,content_type='image/jpg')





class SMSCodeView(View):
    '''短信注册类视图'''
    def post(self, request):
        '''post请求'''
        sms_dict = json.loads(request.body)
        mobile = sms_dict.get('mobile')
        # 将这句话提到前面最开始的位置:
        redis_conn = get_redis_connection('verify_code')
        # 进入函数后, 先获取存储在 redis 中的数据
        send_flag = redis_conn.get('send_flag_%s' % mobile)
        # 查看数据是否存在, 如果存在, 说明60s没过, 返回
        if send_flag:
            return JsonResponse({'errno':'4201',
                                 'errmsg': '发送短信过于频繁'})

        cur_id = sms_dict.get('id')
        image_code_client = sms_dict.get('text')

        if not all([mobile,cur_id,image_code_client]):
            return JsonResponse({"errno": '4103', "errmsg": "缺少必传参数"})

        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({"errno": '4103', "errmsg": "手机号格式错误"})

        # 创建连接到redis的对象
        redis_conn = get_redis_connection('verify_code')

        image_code_server = redis_conn.get('img_%s' % cur_id)

        if image_code_server is None:
            return JsonResponse({'errno':'4002',
                                     'errmsg': '图形验证码失效'})

        # 删除图形验证码，避免恶意测试图形验证码
        try:
            redis_conn.delete('img_%s' % cur_id)
        except Exception as e:
            logger.error(e)

        # 对比图形验证码
        # bytes 转字符串
        image_code_server = image_code_server.decode()
        # 转小写后比较
        if image_code_client.lower() != image_code_server.lower():
            return JsonResponse({'errno':'4004',
                                     'errmsg': '输入图形验证码有误'})

        # 7. 生成短信验证码：生成6位数验证码
        sms_code = '%04d' % random.randint(0, 999999)
        logger.info(sms_code)

        # 8. 保存短信验证码
        # 短信验证码有效期，单位：300秒
        pl = redis_conn.pipeline()
        pl.setex('sms_%s' % mobile, 60*10, sms_code)
        pl.setex('send_flag_%s' % mobile, 60, 1)
        pl.execute()

        # 发送短信验证码
        # 短信模板
        ccp_send_sms_code.delay(mobile, sms_code)

        return JsonResponse({"errno":"0", "errmsg": "ok"})



class RegisterView(View):
    '''定义注册类视图'''
    def post(self,request):

        '''注册接口post请求'''
        user_dict = json.loads(request.body)

        mobile = user_dict.get('mobile')
        phonecode = user_dict.get('phonecode')
        password = user_dict.get('password')

        if not all([mobile,phonecode,password]):
            return JsonResponse({"errno":'4004',"errmsg":"缺少必传参数"})

        # 6.mobile检验
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({'errno':'4004',
                                     'errmsg': 'mobile格式有误'})
        try:
            count = User.objects.filter(mobile=mobile).count()
        except Exception as e:
            return JsonResponse({'errno':'4001',
                                 'errmsg': '查询数据库出错'})
        if count > 0:
            return JsonResponse({'errno':'4003',
                                 'errmsg': '该手机号已注册过'})
        # 4.password检验
        if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
            return JsonResponse({'errno':'4004',
                                     'errmsg': 'password格式有误'})

        # sms_code检验 (链接redis数据库)
        redis_conn = get_redis_connection('verify_code')

        #从redis中取值
        sms_code_server = redis_conn.get('sms_%s' % mobile)
        # 判断该值是否存在
        if not sms_code_server:
            return JsonResponse({'errno':'4002',
                                 'errmsg': '短信验证码过期'})
        if phonecode != sms_code_server.decode():
            return JsonResponse({'errno':'4004',
                                 'errmsg': '验证码有误'})

        # 保存到数据库 (username password mobile)
        try:
            user = User.objects.create_user(username=mobile,mobile=mobile,password=password)
        except Exception as e:
            return JsonResponse({'errno':'4302',
                                     'errmsg': '保存到数据库出错'})

        login(request, user)

        #拼接json返回
        return JsonResponse({'errno':"0",
                                 'errmsg': 'ok'})


class LoginView(View):
    '''登录视图类'''
    def post(self,request):
        '''post请求'''
        user_dict = json.loads(request.body)

        mobile = user_dict.get('mobile')
        password = user_dict.get('password')

        if not all([mobile,password]):
            return JsonResponse({"errno":'4004', "errmsg": "缺少必传参数"})



        user = authenticate(username=mobile,password=password)

        if user is None:
            return JsonResponse({"errno":'4004', "errmsg": "用户名或密码错误"})

        login(request, user)
        request.session.set_expiry(None)

        return JsonResponse({"errno":0, "errmsg": "登录成功"})


    def get(self,request):

        user = request.user

        if user.is_authenticated:

            username = user.username
            return JsonResponse({"errno":0, "errmsg": "已登录","data":{"name":username}})

        else:
            return JsonResponse({"errno": "4101", "errmsg": "未登录"})


    def delete(self, request):
        """实现退出登录逻辑"""

        # 清理 session
        logout(request)

        # 创建 response 对象.
        response = JsonResponse({'errno':0,
                                 'errmsg':"已登出"})

        # 调用对象的 delete_cookie 方法, 清除cookie
        response.delete_cookie('username')

        # 返回响应
        return response


class PersonInfoView(LoginRequiredMixin,View):
    '''个人中心视图类'''
    def get(self,request):
        '''get请求'''
        user = request.user
        avatar = user.avatar.name
        mobile = user.mobile
        user_id = user.id

        data = {
        "avatar":avatar,
        "create_time":user.create_time.strftime('%Y-%m-%d %H:%M:%S'),
        "mobile": mobile,
        "name": user.username,
        "user_id": user_id
        }

        return JsonResponse({"errno":0, "errmsg": "已登录",
                             "data":data})


class AuthenticationView(LoginRequiredMixin,View):
    '''身份信息实名认证'''
    def post(self,request):
        '''
        {
            "errno": "0",
            "errmsg": "认证信息保存成功"
        }
        :param request:
        :return:
        '''
        auth_dict = json.loads(request.body)
        real_name = auth_dict.get('real_name')
        id_card = auth_dict.get('id_card')

        if not all([real_name,id_card]):
            return JsonResponse({"errno":'4103', "errmsg": "缺少必传参数"})

        try:
            count = User.objects.filter(id=request.user.id,id_card=id_card,real_name=real_name).count()
        except Exception as e:
            return JsonResponse({'errno':'4001',
                                 'errmsg': '查询数据库出错'})

        if count > 0:
            data = {"real_name":real_name,"id_card":id_card}
            return JsonResponse({"errno":'0',
                                 "errmsg": "身份信息已存在",
                                 "data":data})

        result = verify_identification_card_info(id_card,real_name)

        if result != "01":
            return JsonResponse({"errno":'4004', "errmsg": "验证失败，身份信息不一致"})

        try:
            User.objects.filter(id=request.user.id).update(id_card=id_card,real_name=real_name)
        except Exception:
            return JsonResponse({"errno": "4004",
                                 "errmsg": "认证信息保存失败"})

        return JsonResponse({"errno": "0",
                                 "errmsg": "认证信息保存成功"})

    def get(self,request):
        '''get请求'''
        user = request.user

        try:
            count = User.objects.filter(id=request.user.id,id_card=user.id_card, real_name=user.real_name).count()
        except Exception as e:
            return JsonResponse({'errno':'4001',
                                 'errmsg': '查询数据库出错'})

        if count > 0:
            data = {"real_name": user.real_name, "id_card": user.id_card}
            return JsonResponse({"errno":'0',
                                 "errmsg": "身份信息已存在",
                                 "data": data})
        else:
            return JsonResponse({"errno": '4004', "errmsg": "身份信息不存在"})


class UploadImageFile(LoginRequiredMixin,View):
    '''上传用户头像类'''


    def post(self,request):
        '''post请求'''
        user_image_head_file = request.FILES.get('avatar')
        if not user_image_head_file:
            return JsonResponse({"errno": "4002", "errmsg": "DATAERR"})
        try:
            # 调用七牛云
            ret = storage(user_image_head_file.read())
            # 保存文件名到数据库中
            avatar = 'http://qerta0kqb.bkt.clouddn.com/' + str(ret)
            User.objects.filter(username=request.user.username).update(avatar=avatar)
        except Exception as e:
            return JsonResponse({"errno": "4301", "errmsg": "THIRDERR"})

        return JsonResponse({'data':{"avatar_url":avatar},
                             'errno':'0',
                             'errmsg':'头像上传成功'})


class Rename(LoginRequiredMixin,View):
    '''修改用户名'''


    def put(self,request):
        a = json.loads(request.body)
        if not a:
            return JsonResponse({'errno':'4002',
                                 'errmsg':'缺少必传参数'})
        name = a.get('name')
        if not re.match(r'[a-zA-Z0-9_-]{5,20}', name):
            return JsonResponse({'errno':'4004',
                                     'errmsg': '用户名格式有误'})

        try:
            count = User.objects.filter(username=name).count()
        except Exception as e:
            return JsonResponse({'code':'4302',
                                 'errmsg': '查询数据库出错'})
        if count > 0:
            return JsonResponse({'code':'4003',
                                 'errmsg': '用户名重复'})

        try:
            # 保存文件名到数据库中
            User.objects.filter(username=request.user.username).update(username=name)
        except Exception as e:
            return JsonResponse({"errno":'4302', "errmsg": "保存失败"})


        return JsonResponse({"errno": "0",
                              "errmsg": "修改成功"})
